﻿using System.Linq;
using System;
using System.IO;

namespace PaperPluginUtilities
{
    static public class General
    {
        /// <summary>
        /// Remove any trailing "/"'s
        /// </summary>
        /// <param name="p"></param>
        /// <param name="p_2"></param>
        /// <returns></returns>
        public static string RemoveTrailing(this string baseStr, string trailingStringToRemove)
        {
            int index = baseStr.LastIndexOf(trailingStringToRemove);
            if (index + trailingStringToRemove.Length == baseStr.Length)
            {
                return baseStr.Substring(0, index);
            }
            return baseStr;
        }

        /// <summary>
        /// Could whatever text we are looking at be a good description of what we want to go for?
        /// 1) Should not be null length
        /// 2) Should not be a file extension
        /// 
        /// This is special case programing at its best (or worst).
        /// </summary>
        /// <param name="innerText"></param>
        /// <returns></returns>
        public static bool IsNotTooSimpleDescription(this string innerText)
        {
            if (innerText == null || innerText.Length == 0)
            {
                return false;
            }

            ///
            /// Look to see if EPS or GIF is in some text we recognize or something
            /// 

            if (innerText.CheckForStringPatternOnValidTypes("", " version")) // eps version
            {
                return false;
            }
            if (innerText.CheckForStringPatternOnValidTypes("", " figure")) // eps figure
            {
                return false;
            }
            if (innerText.CheckForStringPatternOnValidTypes("", " file")) // eps figure
            {
                return false;
            }
            if (innerText.CheckForStringPatternOnValidTypes("", " version of the figure")) // eps version of the figure
            {
                return false;
            }
            if (innerText.CheckForStringPatternOnValidTypes("(", ")")) // (eps)
            {
                return false;
            }
            if (innerText.CheckForStringPatternOnValidTypes("[", "]")) // [eps]
            {
                return false;
            }
            if (innerText.CheckForStringPatternOnValidTypes(".", "")) // .eps
            {
                return false;
            }
            if (innerText.CheckForStringPatternOnValidTypes("Click here for ", " file")) // .eps
            {
                return false;
            }

            ///
            /// Too short!?
            /// 

            if (innerText.Length <= 3)
            {
                return false;
            }

            ///
            /// And if it is a dumb file type or something

            return innerText.NotFileExtension();
        }

        /// <summary>
        /// Some common code to do a quick check to see if there is a particular pattern existing in the
        /// text.
        /// </summary>
        /// <param name="innerText"></param>
        /// <returns></returns>
        private static bool CheckForStringPatternOnValidTypes(this string innerText, string prefix, string postfix)
        {
            return validImageTypes.Any(imgType =>
            {
                var striped = imgType.Substring(1);
                string completeString = prefix + striped + postfix;
                return (innerText.Contains(completeString) && (innerText.Length < completeString.Length + 5));
            });
        }

        /// <summary>
        /// True if the argument is a file extension in discise. :(
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        private static bool NotFileExtension(this string ext)
        {
            return !validImageTypes.Contains("." + ext.ToLower());
        }

        /// <summary>
        /// Is this guy pointing to an image we are going to let through? :-)
        /// </summary>
        /// <param name="u"></param>
        /// <returns></returns>
        public static bool IsImageReference(this Uri u)
        {
            string lastSeg = u.Segments.Last();
            string ext = Path.GetExtension(lastSeg).ToLower();
            return validImageTypes.Contains(ext);
        }

        /// <summary>
        /// Looks in the list of images and figures out what rankign this guy is...
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static int ImageTypeRank(this Uri uri)
        {
            string lastSeg = uri.Segments.Last();
            string ext = Path.GetExtension(lastSeg).ToLower();
            return validImageTypes.TakeWhile(l => l != ext).Count();
        }

        /// <summary>
        /// Is this a folder we are looking at in this url?
        /// </summary>
        /// <param name="renderAddress"></param>
        /// <returns></returns>
        public static bool IsWebFolder(this string renderAddress)
        {
            Uri u = new Uri(renderAddress);
            string last = u.Segments.Last();
            if (!last.Contains("."))
            {
                return true;
            }
            string ext = Path.GetExtension(last);
            if (ext == ".html" || ext == ".htm")
            {
                return false;
            }
            if (validImageTypes.Contains(ext))
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// List of valid image file types.
        /// </summary>
        private static string[] validImageTypes = {".png", ".jpg", ".jpeg", ".ps", ".eps", ".pdf", ".gif" };

        /// <summary>
        /// Removes things like [.png] or [png] from a string. Does this over all images. Trims the
        /// resulting string too.
        /// </summary>
        /// <param name="descr"></param>
        /// <returns></returns>
        public static string RemoveImageReferences(this string descr)
        {
            string result = descr;
            foreach (var ext in validImageTypes)
            {
                result = result.Replace("[" + ext + "]", "");
                result = result.Replace("[" + ext.Substring(1) + "]", "");
            }
            return result.Trim();

        }

        /// <summary>
        /// How long will we allow pivot image names to be?
        /// </summary>
        private const int MaxNameLength = 40;

        /// <summary>
        /// GIven a list of names (in priority order) find oen that works. If all else fails, then extract
        /// the actual name from the Uri we are pointing to.
        /// </summary>
        /// <param name="possibleNames"></param>
        /// <param name="imageUri"></param>
        /// <returns></returns>
        public static string DecideOnImageName(string[] possibleNames, Uri imageUri)
        {
            foreach (var item in possibleNames)
            {
                if (item.IsNotTooSimpleDescription() && item.Length < MaxNameLength && item.Length > 0)
                {
                    return item;
                }
            }
            
            ///
            /// None of the names worked. Now use the url... buch check its length too!
            /// 


            string name = imageUri.ImageFileStem();
            if (name.Length > MaxNameLength) {
                name = name.Substring(0, MaxNameLength);
            }

            return name;
        }

        /// <summary>
        /// Gets the filename stem of the image we are pointing to here
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static string ImageFileStem(this Uri uri)
        {
            string lastSeg = uri.Segments.Last();
            return Path.GetFileNameWithoutExtension(lastSeg);
        }
    }
}
